package com.mida.dms.knw.service.impl;

import com.mida.dms.knw.entity.*;
import com.mida.dms.knw.entity.vo.*;
import com.mida.dms.knw.entity.vo.KnwNoumenonVo;
import com.mida.dms.knw.mapper.*;
import com.mida.dms.knw.Result.BaseResult;
import com.mida.dms.knw.service.KnwNoumenonRelationService;
import com.mida.dms.knw.service.SoidService;
import com.mida.dms.knw.vo.*;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class KnwNoumenonRelationServiceImpl extends BaseResult implements KnwNoumenonRelationService {

    @Autowired
    private SoidService soidService;

    @Autowired
    private KnwNoumenonRelationMapper relationMapper;

    @Autowired
    private KnwNoumenonMapper knwNoumenonMapper;

    @Autowired
    private KnwConceptualDetailMapper detailMapper;

    @Autowired
    private KnwConceptualMapper knwConceptualMapper;

    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult add(KnwNoumenonRelationVo relation) {
        log.info("开始新增本体关系" + relation.toString());
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            KnwNoumenon knwNoumenon = knwNoumenonMapper.selectByPrimaryKey(relation.getThisNoumenonSoid());
            if (knwNoumenon != null) {
                if (knwNoumenon.getStatus().longValue() != 145L) {
                    buildBadRequestActionWarn(actionResult, "非启用状态本体不能建立本体关系");
                    return actionResult;
                }
            }

            if (ObjectUtils.isEmpty(relation.getSourceNoumenonSoid())) {
                buildBadRequestActionWarn(actionResult, "源本体不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getTargetNoumenonSoid())) {
                buildBadRequestActionWarn(actionResult, "目标本体不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getConceptualSoid())) {
                buildBadRequestActionWarn(actionResult, "关系名称不能为空");
                return actionResult;
            }

            //源本体和目标本体不包含当前本体
            if (relation.getThisNoumenonSoid().compareTo(relation.getSourceNoumenonSoid()) != 0 &&
                    relation.getThisNoumenonSoid().compareTo(relation.getTargetNoumenonSoid()) != 0) {
                buildBadRequestActionWarn(actionResult, "源本体和目标本体不包含当前本体");
                return actionResult;
            }

            if (relation.getSourceNoumenonSoid().compareTo(relation.getTargetNoumenonSoid()) == 0) {
                buildBadRequestActionWarn(actionResult, "源本体和目标本体不可相同");
                return actionResult;
            }

            //关系查重
            int count = relationMapper.selectDistinct(relation.getSourceNoumenonSoid(), relation.getTargetNoumenonSoid(), relation.getConceptualSoid());
            if (count > 0) {
                buildBadRequestActionWarn(actionResult, "关系已存在");
                return actionResult;
            }

            //检查关系是否闭环
            List<Long> sensitiveIdList = new ArrayList<>();
            List<Long> idList = relationMapper.selectRelationByTargetSoid(relation.getSourceNoumenonSoid());
            collectSensitiveId(idList, sensitiveIdList);
            if (sensitiveIdList.contains(relation.getTargetNoumenonSoid())) {
                buildBadRequestActionWarn(actionResult, "源本体和目标本体形成闭环");
                return actionResult;
            }

            //新增业务操作
//            Long soid = oIDGanerator.getSOID();
            Long soid = soidService.getSoid();
            relation.setNoumenonRelationSoid(soid);
            relation.setCreateDate(new Date());
            relation.setUpdateDate(new Date());
            relation.setIsDelete(0L);
            relation.setStatus(145L);

            relation.setConceptualSoid(relation.getConceptualSoid());
            KnwNoumenonRelation knwNoumenonRelation = convertVoToRelation(relation);
            relationMapper.insert(knwNoumenonRelation);

            //国标
            soidService.insertOid(soid, 1);

            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("新增关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "新增关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次新增耗时:" + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult updateSingle(KnwNoumenonRelationVo relation) {
        log.info("开始更新本体关系" + relation.toString());
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            KnwNoumenon knwNoumenon = knwNoumenonMapper.selectByPrimaryKey(relation.getThisNoumenonSoid());
            if (knwNoumenon != null) {
                if (knwNoumenon.getStatus().longValue() != 145L) {
                    buildBadRequestActionWarn(actionResult, "非启用状态本体不能建立本体关系");
                    return actionResult;
                }
            }

            if (ObjectUtils.isEmpty(relation.getSourceNoumenonSoid())) {
                buildBadRequestActionWarn(actionResult, "源本体不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getTargetNoumenonSoid())) {
                buildBadRequestActionWarn(actionResult, "目标本体不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getConceptualSoid())) {
                buildBadRequestActionWarn(actionResult, "关系名称不能为空");
                return actionResult;
            }

            //源本体和目标本体不包含当前本体
            if (relation.getThisNoumenonSoid().compareTo(relation.getSourceNoumenonSoid()) != 0 &&
                    relation.getThisNoumenonSoid().compareTo(relation.getTargetNoumenonSoid()) != 0) {
                buildBadRequestActionWarn(actionResult, "源本体和目标本体不包含当前本体");
                return actionResult;
            }

            if (relation.getSourceNoumenonSoid().compareTo(relation.getTargetNoumenonSoid()) == 0) {
                buildBadRequestActionWarn(actionResult, "源本体和目标本体不可相同");
                return actionResult;
            }

            KnwNoumenonRelation knwNoumenonRelationDistinct = relationMapper.selectByPrimaryKey(relation.getNoumenonRelationSoid());
            if (knwNoumenonRelationDistinct != null) {
                if (knwNoumenonRelationDistinct.getSourceNoumenonSoid() != null && knwNoumenonRelationDistinct.getTargetNoumenonSoid() != null && knwNoumenonRelationDistinct.getConceptualSoid() != null) {
                    if (relation.getSourceNoumenonSoid().longValue() != knwNoumenonRelationDistinct.getSourceNoumenonSoid().longValue() ||
                            relation.getTargetNoumenonSoid().longValue() != knwNoumenonRelationDistinct.getTargetNoumenonSoid().longValue() ||
                            relation.getConceptualSoid().longValue() != knwNoumenonRelationDistinct.getConceptualSoid().longValue()) {
                        //关系查重
                        int count = relationMapper.selectDistinct(relation.getSourceNoumenonSoid(), relation.getTargetNoumenonSoid(), relation.getConceptualSoid());
                        if (count > 0) {
                            buildBadRequestActionWarn(actionResult, "关系已存在");
                            return actionResult;
                        }

                        //检查关系是否闭环
                        List<Long> sensitiveIdList = new ArrayList<>();
                        List<Long> idList = relationMapper.selectRelationByTargetSoid(relation.getSourceNoumenonSoid());
                        collectSensitiveId(idList, sensitiveIdList);
                        if (sensitiveIdList.contains(relation.getTargetNoumenonSoid())) {
                            buildBadRequestActionWarn(actionResult, "源本体和目标本体形成闭环");
                            return actionResult;
                        }
                    }
                }
            }

            //更新业务操作
            KnwNoumenonRelation target = new KnwNoumenonRelation();
            BeanUtils.copyProperties(relation, target);
            relationMapper.updateByPrimaryKeySelective(target);
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("更新本体关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "更新本体关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次更新耗时:" + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult delete(Long soid) {
        log.info("开始删除本体关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            if (ObjectUtils.isEmpty(soid)) {
                buildBadRequestActionWarn(actionResult, "本体关系soid不能为空");
                return actionResult;
            }
            relationMapper.deleteByPrimaryKey(soid);
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("删除本体关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "删除本体关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次删除本体关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    @Override
    public ListResult<List<KnwNoumenonVo>> findSourceAndTarget(MapperPage mapperPage) {
        log.info("源本体目标本体下拉查询: " + mapperPage.toString());
        StopWatch st = StopWatch.createStarted();
        ListResult result = new ListResult();
        //获取启用的本体id
        List<Long> idList = knwNoumenonMapper.getNoumenonIdList(mapperPage);
        List<KnwNoumenonVo> knwNoumenonVos = new ArrayList<>();
        if (!idList.isEmpty()) {
            //本体整合成下拉框
            knwNoumenonVos = knwNoumenonMapper.selectNoumenons(idList);
            buildListSuccess(result, knwNoumenonVos);
            return result;
        }
        buildListSuccess(result, new ArrayList<>(0));
        return result;
    }

    @Override
    public ListResult<PageResultVo<KnwNoumenonRelationVo>> findPage(KnwNoumenonRelationPageVo vo) {
        log.info("开始本体关系分页查询,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        PageResultVo pageResultVo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());
        pageResultVo.setPage(page);
        StopWatch stopWatch = StopWatch.createStarted();

        List<KnwNoumenonRelationVo> list = null;
        try {
            KnwNoumenonRelationPage npage = new KnwNoumenonRelationPage(vo.getCurrentPage(), vo.getPageSize(), vo.getSearchData());
            //根据本体ID,本体名称,拼音码,五笔码模糊查询
            int count = relationMapper.findPageCount(npage);
            if (count > 0) {
                page.setTotalCount(count);
                list = relationMapper.findRelationPage(npage);
            } else {
                page.setTotalCount(count);
                list = new ArrayList<KnwNoumenonRelationVo>(0);
            }
            pageResultVo.setList(list);
            buildListSuccess(result, pageResultVo);
        } catch (Exception e) {
            list = new ArrayList<KnwNoumenonRelationVo>(0);
            pageResultVo.setList(list);
            log.error("分页查询本体关系发送异常");
            buildListWarn(result, "分页查询本体关系发送失败");
        } finally {
            stopWatch.stop();
            log.info("本次分页查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }

    @Override
    public ActionResult enable(Long soid) {
        log.info("开始启用一个本体关系: " + soid);
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            KnwNoumenonRelation knwNoumenonRelation = relationMapper.selectByPrimaryKey(soid);
            if (knwNoumenonRelation == null) {
                buildBadRequestActionWarn(actionResult, "本体关系不存在");
                return actionResult;
            }
            if (knwNoumenonRelation.getStatus() == 146L) {
                relationMapper.enable(soid);
            } else if (knwNoumenonRelation.getStatus() == 145L) {
                relationMapper.disable(soid);
            }
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("启用(停用)本体关系发送异常", e);
            buildActionWarn(actionResult, "启用(停用)本体关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次启用(停用)耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    @Override
    public ListResult<Object> findRelation(String searchData) {
        log.info("开始查询关系下拉列表");
        StopWatch st = StopWatch.createStarted();
        ListResult result = new ListResult();
        List<PullDownMenuVO> targetList;
        try {
            HashMap<String, Object> map = new HashMap<>();
            if (StringUtils.isNotEmpty(searchData)) {
                map.put("searChData", searchData.trim().toUpperCase());
            }
            List<KnwConceptualVo> list = knwConceptualMapper.findAll(map);
            if (CollectionUtils.isNotEmpty(list)) {
                targetList = list.stream()
                    .filter(Objects::nonNull)
                    .map(detail -> new PullDownMenuVO(detail.getConceptualSoid(), detail.getConceptualDetailName(), null))
                    .collect(Collectors.toList());
            }else {
                targetList = new ArrayList<>(0);
            }

            buildListSuccess(result, targetList);
        } catch (Exception e) {
            log.error("查询关系下拉列表异常", e);
            buildListWarn(result, "查询关系下拉列表失败");
        } finally {
            st.stop();
            log.info("本次查询耗时:" + st.getTime() + "ms");
        }
        return result;
    }

    public KnwNoumenonRelation convertVoToRelation(KnwNoumenonRelationVo knwNoumenonRelationVo) {
        KnwNoumenonRelation knwNoumenonRelation = new KnwNoumenonRelation();
        knwNoumenonRelation.setNoumenonRelationSoid(knwNoumenonRelationVo.getNoumenonRelationSoid());
        knwNoumenonRelation.setSourceNoumenonSoid(knwNoumenonRelationVo.getSourceNoumenonSoid());
        knwNoumenonRelation.setTargetNoumenonSoid(knwNoumenonRelationVo.getTargetNoumenonSoid());
        knwNoumenonRelation.setConceptualSoid(knwNoumenonRelationVo.getConceptualSoid());
        knwNoumenonRelation.setCreateDate(knwNoumenonRelationVo.getCreateDate());
        knwNoumenonRelation.setUpdateDate(knwNoumenonRelationVo.getUpdateDate());
        knwNoumenonRelation.setUpdateUser(knwNoumenonRelationVo.getUpdateUser());
        knwNoumenonRelation.setIsDelete(knwNoumenonRelationVo.getIsDelete());
        knwNoumenonRelation.setStatus(knwNoumenonRelationVo.getStatus());
        return knwNoumenonRelation;
    }


    //递归收集会产生闭环的本体id
    public void collectSensitiveId(List<Long> tempList, List<Long> resultList) {
        if (tempList == null) {
            return;
        } else {
            resultList.addAll(tempList);
            for (Long i : tempList) {
                List<Long> list = relationMapper.selectRelationByTargetSoid(i);
                collectSensitiveId(list, resultList);
            }
        }
    }

}
